package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"os/signal"
	"strings"

	"time"

	"github.com/dgrijalva/jwt-go"
	"github.com/gin-gonic/gin"
	"github.com/go-redis/redis"
)

const (
	TOKEN_PREFIX    = "Bearer "
	LOGIN_TOKEN_KEY = "login_tokens:"
)

func main() {
	r := gin.Default()
	//jwt secret
	KEY := os.Getenv("secret")

	redisclient := redis.NewClient(&redis.Options{
		Addr:     os.Getenv("redis_host") + ":" + os.Getenv("redis_port"),
		Password: os.Getenv("redis_password"), // no password set
		DB:       0,                           // use default DB
	})

	pong, err := redisclient.Ping().Result()
	log.Println(pong)
	if err != nil {

		log.Println(err)

		return
	}
	defer redisclient.Close()

	gin.SetMode(gin.ReleaseMode)
	f, _ := os.Create("gin.log")
	gin.DefaultWriter = io.MultiWriter(f)

	//设置路由和方法
	r.GET("/jwt_auth", func(c *gin.Context) {
		Authorization := c.GetHeader("Authorization")
		jwt_token := strings.Replace(Authorization, TOKEN_PREFIX, "", 1)

		token, _ := jwt.Parse(jwt_token, func(token *jwt.Token) (interface{}, error) {
			// Don't forget to validate the alg is what you expect:
			if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
				return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
			}
			// hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
			return []byte(KEY), nil
		})
		if token == nil {
			c.JSON(401, gin.H{
				"message": "token分析失败",
			})
			return
		}
		claims, ok := token.Claims.(jwt.MapClaims)
		if ok {
			uuid := claims["login_user_key"].(string)
			userKey := LOGIN_TOKEN_KEY + uuid

			v, _ := redisclient.Get(userKey).Result()
			if v == "" {
				c.JSON(401, gin.H{
					"message": "登录超时,获取用户信息失败",
				})
				return
			} else {
				//解析loginUser
				v = strings.Replace(v, "Set[", "[", 1)
				b := []byte(v)
				m := make(map[string]interface{})
				err = json.Unmarshal(b, &m)
				if err != nil {
					c.JSON(401, gin.H{
						"message": "json解析:" + err.Error(),
					})
					return
				} else {
					//过期时间
					expireTime := int64(m["expireTime"].(float64))
					if time.Now().Unix() > expireTime {
						c.JSON(401, gin.H{
							"message": "token超时",
						})
						return
					}
				}

			}

		} else {
			c.JSON(401, gin.H{
				"message": "获取信息失败",
			})
			return
		}

		c.JSON(200, gin.H{
			"message": "success",
		})
	})

	go func() {
		_ = r.Run(":9033")
	}()

	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	log.Print("end function")
}
